<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>轴承监测系统</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/echarts/5.4.2/echarts.min.js"></script>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 20px;
            background-color: #f5f5f5;
        }
        .container {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 20px;
        }
        .bearing-panel {
            background-color: white;
            border-radius: 8px;
            box-shadow: 0 2px 8px rgba(0,0,0,0.1);
            padding: 15px;
            margin-bottom: 20px;
        }
        .bearing-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 15px;
            padding-bottom: 10px;
            border-bottom: 1px solid #eee;
        }
        .bearing-title {
            font-size: 18px;
            font-weight: bold;
        }
        .alert-status {
            padding: 5px 10px;
            border-radius: 4px;
            font-weight: bold;
        }
        .alert-normal {
            background-color: #d4edda;
            color: #155724;
        }
        .alert-warning {
            background-color: #fff3cd;
            color: #856404;
        }
        .alert-danger {
            background-color: #f8d7da;
            color: #721c24;
        }
        .chart-container {
            height: 300px;
            margin-bottom: 20px;
        }
        .audio-features {
            display: grid;
            grid-template-columns: repeat(3, 1fr);
            gap: 10px;
        }
        .feature-box {
            background-color: #f8f9fa;
            padding: 8px;
            border-radius: 4px;
            font-size: 14px;
        }
        .feature-name {
            font-weight: bold;
            margin-bottom: 5px;
        }
        .feature-value {
            color: #6c757d;
        }
        .probability-bar {
            height: 20px;
            background-color: #e9ecef;
            border-radius: 4px;
            margin-top: 5px;
            overflow: hidden;
        }
        .probability-fill {
            height: 100%;
            background-color: #28a745;
            width: 0%;
            transition: width 0.3s ease, background-color 0.3s ease;
        }
        .probability-fill.warning {
            background-color: #ffc107;
        }
        .probability-fill.danger {
            background-color: #dc3545;
        }
        h1 {
            text-align: center;
            color: #333;
            margin-bottom: 30px;
        }
    </style>
</head>
<body>
    <h1>轴承监测系统</h1>
    <div class="container">
        <div class="bearing-panel" id="bearing-1">
            <div class="bearing-header">
                <div class="bearing-title">轴承 #1</div>
                <div class="alert-status alert-normal" id="bearing-1-status">正常</div>
            </div>
            <div class="chart-container" id="bearing-1-acceleration"></div>
            <div class="chart-container" id="bearing-1-velocity"></div>
            <div class="chart-container" id="bearing-1-temperature"></div>
            <div class="chart-container" id="bearing-1-audio"></div>
            <div class="audio-features" id="bearing-1-features"></div>
            <div style="margin-top: 15px;">
                <div>故障概率: <span id="bearing-1-probability">0%</span></div>
                <div class="probability-bar">
                    <div class="probability-fill" id="bearing-1-probability-bar"></div>
                </div>
            </div>
        </div>

        <div class="bearing-panel" id="bearing-2">
            <div class="bearing-header">
                <div class="bearing-title">轴承 #2</div>
                <div class="alert-status alert-normal" id="bearing-2-status">正常</div>
            </div>
            <div class="chart-container" id="bearing-2-acceleration"></div>
            <div class="chart-container" id="bearing-2-velocity"></div>
            <div class="chart-container" id="bearing-2-temperature"></div>
            <div class="chart-container" id="bearing-2-audio"></div>
            <div class="audio-features" id="bearing-2-features"></div>
            <div style="margin-top: 15px;">
                <div>故障概率: <span id="bearing-2-probability">0%</span></div>
                <div class="probability-bar">
                    <div class="probability-fill" id="bearing-2-probability-bar"></div>
                </div>
            </div>
        </div>

        <div class="bearing-panel" id="bearing-3">
            <div class="bearing-header">
                <div class="bearing-title">轴承 #3</div>
                <div class="alert-status alert-normal" id="bearing-3-status">正常</div>
            </div>
            <div class="chart-container" id="bearing-3-acceleration"></div>
            <div class="chart-container" id="bearing-3-velocity"></div>
            <div class="chart-container" id="bearing-3-temperature"></div>
            <div class="chart-container" id="bearing-3-audio"></div>
            <div class="audio-features" id="bearing-3-features"></div>
            <div style="margin-top: 15px;">
                <div>故障概率: <span id="bearing-3-probability">0%</span></div>
                <div class="probability-bar">
                    <div class="probability-fill" id="bearing-3-probability-bar"></div>
                </div>
            </div>
        </div>

        <div class="bearing-panel" id="bearing-4">
            <div class="bearing-header">
                <div class="bearing-title">轴承 #4</div>
                <div class="alert-status alert-normal" id="bearing-4-status">正常</div>
            </div>
            <div class="chart-container" id="bearing-4-acceleration"></div>
            <div class="chart-container" id="bearing-4-velocity"></div>
            <div class="chart-container" id="bearing-4-temperature"></div>
            <div class="chart-container" id="bearing-4-audio"></div>
            <div class="audio-features" id="bearing-4-features"></div>
            <div style="margin-top: 15px;">
                <div>故障概率: <span id="bearing-4-probability">0%</span></div>
                <div class="probability-bar">
                    <div class="probability-fill" id="bearing-4-probability-bar"></div>
                </div>
            </div>
        </div>
    </div>

    <script>
        // 初始化数据存储
        const bearingData = {
            1: { acceleration: [], velocity: [], temperature: [], audio: [], features: {}, probability: 0 },
            2: { acceleration: [], velocity: [], temperature: [], audio: [], features: {}, probability: 0 },
            3: { acceleration: [], velocity: [], temperature: [], audio: [], features: {}, probability: 0 },
            4: { acceleration: [], velocity: [], temperature: [], audio: [], features: {}, probability: 0 }
        };

        // 初始化图表
        const charts = {};

        function initCharts() {
            for (let i = 1; i <= 4; i++) {
                // 加速度图表
                charts[`bearing-${i}-acceleration`] = echarts.init(document.getElementById(`bearing-${i}-acceleration`));
                charts[`bearing-${i}-acceleration`].setOption({
                    title: { text: '三轴加速度 (m/s²)', left: 'center' },
                    tooltip: { trigger: 'axis' },
                    legend: { data: ['X轴', 'Y轴', 'Z轴'], bottom: 0 },
                    xAxis: { type: 'category', boundaryGap: false },
                    yAxis: { type: 'value', name: '加速度 (m/s²)' },
                    series: [
                        { name: 'X轴', type: 'line', showSymbol: false },
                        { name: 'Y轴', type: 'line', showSymbol: false },
                        { name: 'Z轴', type: 'line', showSymbol: false }
                    ]
                });

                // 速度图表
                charts[`bearing-${i}-velocity`] = echarts.init(document.getElementById(`bearing-${i}-velocity`));
                charts[`bearing-${i}-velocity`].setOption({
                    title: { text: '三轴速度 (mm/s)', left: 'center' },
                    tooltip: { trigger: 'axis' },
                    legend: { data: ['X轴', 'Y轴', 'Z轴'], bottom: 0 },
                    xAxis: { type: 'category', boundaryGap: false },
                    yAxis: { type: 'value', name: '速度 (mm/s)' },
                    series: [
                        { name: 'X轴', type: 'line', showSymbol: false },
                        { name: 'Y轴', type: 'line', showSymbol: false },
                        { name: 'Z轴', type: 'line', showSymbol: false }
                    ]
                });

                // 温度图表
                charts[`bearing-${i}-temperature`] = echarts.init(document.getElementById(`bearing-${i}-temperature`));
                charts[`bearing-${i}-temperature`].setOption({
                    title: { text: '温度 (°C)', left: 'center' },
                    tooltip: { trigger: 'axis' },
                    xAxis: { type: 'category', boundaryGap: false },
                    yAxis: { type: 'value', name: '温度 (°C)' },
                    series: [
                        { name: '温度', type: 'line', showSymbol: false, areaStyle: {} }
                    ]
                });

                // 音频特征图表
                charts[`bearing-${i}-audio`] = echarts.init(document.getElementById(`bearing-${i}-audio`));
                charts[`bearing-${i}-audio`].setOption({
                    title: { text: '音频特征', left: 'center' },
                    tooltip: { trigger: 'axis' },
                    legend: {
                        data: ['peak', 'peak_peak', 'rms', 'kurtosis', 'skewness', 'crest_factor',
                               'impulse_factor', 'clearance_factor', 'shape_factor', 'var', 'std', 'mean'],
                        bottom: 0,
                        type: 'scroll',
                        padding: 5
                    },
                    xAxis: { type: 'category', boundaryGap: false },
                    yAxis: { type: 'value', name: '值' },
                    series: [
                        { name: 'peak', type: 'line', showSymbol: false },
                        { name: 'peak_peak', type: 'line', showSymbol: false },
                        { name: 'rms', type: 'line', showSymbol: false },
                        { name: 'kurtosis', type: 'line', showSymbol: false },
                        { name: 'skewness', type: 'line', showSymbol: false },
                        { name: 'crest_factor', type: 'line', showSymbol: false },
                        { name: 'impulse_factor', type: 'line', showSymbol: false },
                        { name: 'clearance_factor', type: 'line', showSymbol: false },
                        { name: 'shape_factor', type: 'line', showSymbol: false },
                        { name: 'var', type: 'line', showSymbol: false },
                        { name: 'std', type: 'line', showSymbol: false },
                        { name: 'mean', type: 'line', showSymbol: false }
                    ]
                });
            }
        }

        // 更新图表数据
        function updateChart(bearingId, chartType, data) {
            const chartId = `bearing-${bearingId}-${chartType}`;
            const chart = charts[chartId];

            if (!chart) return;

            let option = chart.getOption();

            // 限制数据量为100条
            if (data.length > 100) {
                data = data.slice(data.length - 100);
            }

            // 生成时间戳作为x轴数据
            const timestamps = data.map((_, index) => {
                const now = new Date();
                now.setSeconds(now.getSeconds() - (100 - index));
                return now.toLocaleTimeString();
            });

            option.xAxis[0].data = timestamps;

            if (chartType === 'acceleration') {
                option.series[0].data = data.map(d => d.x);
                option.series[1].data = data.map(d => d.y);
                option.series[2].data = data.map(d => d.z);
            } else if (chartType === 'velocity') {
                option.series[0].data = data.map(d => d.x);
                option.series[1].data = data.map(d => d.y);
                option.series[2].data = data.map(d => d.z);
            } else if (chartType === 'temperature') {
                option.series[0].data = data;
            } else if (chartType === 'audio') {
                const featureNames = ['peak', 'peak_peak', 'rms', 'kurtosis', 'skewness', 'crest_factor',
                                    'impulse_factor', 'clearance_factor', 'shape_factor', 'var', 'std', 'mean'];

                featureNames.forEach((feature, index) => {
                    option.series[index].data = data.map(d => d[feature]);
                });
            }

            chart.setOption(option);
        }

        // 更新音频特征显示
        function updateAudioFeatures(bearingId, features) {
            const container = document.getElementById(`bearing-${bearingId}-features`);
            container.innerHTML = '';

            for (const [name, value] of Object.entries(features)) {
                const featureBox = document.createElement('div');
                featureBox.className = 'feature-box';

                const featureName = document.createElement('div');
                featureName.className = 'feature-name';
                featureName.textContent = name;

                const featureValue = document.createElement('div');
                featureValue.className = 'feature-value';
                featureValue.textContent = value.toFixed(4);

                featureBox.appendChild(featureName);
                featureBox.appendChild(featureValue);
                container.appendChild(featureBox);
            }
        }

        // 更新故障概率显示
        function updateProbability(bearingId, probability) {
            const probabilityElement = document.getElementById(`bearing-${bearingId}-probability`);
            const probabilityBar = document.getElementById(`bearing-${bearingId}-probability-bar`);
            const statusElement = document.getElementById(`bearing-${bearingId}-status`);

            const percentage = Math.round(probability * 100);
            probabilityElement.textContent = `${percentage}%`;
            probabilityBar.style.width = `${percentage}%`;

            // 更新状态显示
            if (probability > 0.5) {
                statusElement.textContent = '故障预警';
                statusElement.className = 'alert-status alert-danger';
                probabilityBar.className = 'probability-fill danger';
            } else if (probability > 0.3) {
                statusElement.textContent = '注意';
                statusElement.className = 'alert-status alert-warning';
                probabilityBar.className = 'probability-fill warning';
            } else {
                statusElement.textContent = '正常';
                statusElement.className = 'alert-status alert-normal';
                probabilityBar.className = 'probability-fill';
            }
        }

        // 模拟数据更新
        function simulateDataUpdate() {
            for (let i = 1; i <= 4; i++) {
                // 生成随机加速度数据 (m/s²)
                const acceleration = {
                    x: Math.random() * 2,
                    y: Math.random() * 2,
                    z: Math.random() * 2
                };

                // 生成随机速度数据 (mm/s)
                const velocity = {
                    x: Math.random() * 10,
                    y: Math.random() * 10,
                    z: Math.random() * 10
                };

                // 生成随机温度数据 (°C)
                const temperature = 30 + Math.random() * 20;

                // 生成随机音频特征
                const audioFeatures = {
                    peak: Math.random() * 10,
                    peak_peak: Math.random() * 20,
                    rms: Math.random() * 5,
                    kurtosis: Math.random() * 10,
                    skewness: (Math.random() - 0.5) * 2,
                    crest_factor: 1 + Math.random() * 4,
                    impulse_factor: 1 + Math.random() * 4,
                    clearance_factor: 1 + Math.random() * 4,
                    shape_factor: 1 + Math.random() * 2,
                    var: Math.random() * 10,
                    std: Math.random() * 3,
                    mean: (Math.random() - 0.5) * 2
                };

                // 生成随机故障概率 (0-1)
                let probability = Math.random() * 0.6;
                // 让轴承4有更高概率出现故障
                if (i === 4 && Math.random() > 0.7) {
                    probability = 0.5 + Math.random() * 0.5;
                }

                // 更新数据存储
                bearingData[i].acceleration.push(acceleration);
                bearingData[i].velocity.push(velocity);
                bearingData[i].temperature.push(temperature);
                bearingData[i].audio.push(audioFeatures);
                bearingData[i].features = audioFeatures;
                bearingData[i].probability = probability;

                // 更新图表
                updateChart(i, 'acceleration', bearingData[i].acceleration);
                updateChart(i, 'velocity', bearingData[i].velocity);
                updateChart(i, 'temperature', bearingData[i].temperature);
                updateChart(i, 'audio', bearingData[i].audio);

                // 更新音频特征显示
                updateAudioFeatures(i, audioFeatures);

                // 更新故障概率显示
                updateProbability(i, probability);
            }
        }

        // 初始化
        document.addEventListener('DOMContentLoaded', () => {
            initCharts();

            // 初始数据
            for (let i = 1; i <= 4; i++) {
                // 填充初始数据
                for (let j = 0; j < 20; j++) {
                    const acceleration = {
                        x: Math.random() * 2,
                        y: Math.random() * 2,
                        z: Math.random() * 2
                    };

                    const velocity = {
                        x: Math.random() * 10,
                        y: Math.random() * 10,
                        z: Math.random() * 10
                    };

                    const temperature = 30 + Math.random() * 20;

                    const audioFeatures = {
                        peak: Math.random() * 10,
                        peak_peak: Math.random() * 20,
                        rms: Math.random() * 5,
                        kurtosis: Math.random() * 10,
                        skewness: (Math.random() - 0.5) * 2,
                        crest_factor: 1 + Math.random() * 4,
                        impulse_factor: 1 + Math.random() * 4,
                        clearance_factor: 1 + Math.random() * 4,
                        shape_factor: 1 + Math.random() * 2,
                        var: Math.random() * 10,
                        std: Math.random() * 3,
                        mean: (Math.random() - 0.5) * 2
                    };

                    bearingData[i].acceleration.push(acceleration);
                    bearingData[i].velocity.push(velocity);
                    bearingData[i].temperature.push(temperature);
                    bearingData[i].audio.push(audioFeatures);
                    bearingData[i].features = audioFeatures;
                    bearingData[i].probability = Math.random() * 0.3;
                }

                // 更新初始图表
                updateChart(i, 'acceleration', bearingData[i].acceleration);
                updateChart(i, 'velocity', bearingData[i].velocity);
                updateChart(i, 'temperature', bearingData[i].temperature);
                updateChart(i, 'audio', bearingData[i].audio);

                // 更新初始音频特征显示
                updateAudioFeatures(i, bearingData[i].features);

                // 更新初始故障概率显示
                updateProbability(i, bearingData[i].probability);
            }

            // 设置定时更新
            setInterval(simulateDataUpdate, 1000);

            // 窗口大小变化时重新调整图表大小
            window.addEventListener('resize', () => {
                for (const chartId in charts) {
                    charts[chartId].resize();
                }
            });
        });
    </script>
</body>
</html>